import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;

class GameBody extends JPanel implements KeyListener {
    private int shapeType=-1;  //定义方块的类型  定义的为7种
    private int shapeState=-1; //定义方块为何种状态，每种都有四种状态
    private int nextshapeType=-1;  //定义下一块产生的类型
    private int nextshapeState=-1;  //定义下一块的方块的状态
    private final int CELL=25;   //定义方格的大小
    int score=0;    //定义显示的成绩
    private int left;       //定义初始图形与两边的墙的距离
    private int top;        //定义初始图形与上下墙的距离
    private int i=0;        //表示列
    private int j=0;        //表示行
    public int flag=0;
    public  volatile boolean start=false;  //暂停的判断条件，为轻量锁，保持同步的
    Random randomcolor=new Random();
    Random random=new Random();
    //定义地图的大小，创建二位的数组
    int[][] map=new int[13][23];

    //初始化地图
    public void resetMap(){
        for(i=0;i<12;i++){
            for(j=0;j<22;j++){  //遍历的范围不能小
                map[i][j]=0;
            }
        }
    }

    //画围墙的方法
    public void drawWall(){
        for(j=0;j<22;j++)  //0到21行
        {
            map[0][j]=2;
            map[11][j]=2;    //第0行和第11行为墙
        }
        for(i=0;i<12;i++){  //0到11列
            map[i][21]=2;    //第21行划墙
        }
    }

    private final int[][][] shapes=new int[][][]{
            // i
            {       { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
                    { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
                    { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
                    { 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 } },
            // s
            {		{ 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                    { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
                    { 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                    { 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 } },
            // z
            {		{ 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                    { 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
                    { 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                    { 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 } },
            // j
            {		{ 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },
                    { 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                    { 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
                    { 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
            // o
            {		{ 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                    { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                    { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                    { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
            // l
            {		{ 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },
                    { 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                    { 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
                    { 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
            // t
            {		{ 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                    { 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
                    { 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
                    { 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 } }
    };
    //产生新图形的方法
    public void createshape(){
        if(shapeType==-1&&shapeState==-1){
            shapeType = random.nextInt(shapes.length);
            shapeState = random.nextInt(shapes[0].length);
        }else{
            shapeType=nextshapeType;
            shapeState=nextshapeState;
        }
        nextshapeType = random.nextInt(shapes.length);
        nextshapeState = random.nextInt(shapes[0].length);
        //shapeType=(int)(Math.random()*1000)%7;   //在7中类型中随机选取
        //shapeState=(int)(Math.random()*1000)%4;  //在四种状态中随机选取
        left=4; top=0;  //图形产生的初始位置为（4,0）
        if(gameOver(left,top)==1){
            resetMap();
            drawWall();
            score=0;
            JOptionPane.showMessageDialog(null, "GAME OVER");
        }
    }
    //遍历[4][4]数组产生的方块并判断状态
    public int judgeState(int left,int top,int shapeType,int shapeState){
        for(int a=0;a<4;a++){
            for(int b=0;b<4;b++){
                if(((shapes[shapeType][shapeState][a*4+b]==1 &&   //遍历数组中为1的个数，即判断是否有图形
                        map[left+b+1][top+a]==1))||                   //判断地图中是否还有障碍物
                        ((shapes[shapeType][shapeState][a*4+b]==1 &&   //遍历数组中为1的个数，即判断是否有图形
                                map[left+b+1][top+a]==2))){                   //判断是否撞墙
                    return 0;    //表明无法不能正常运行
                }
            }
        }
        return 1;
    }

    public void keyPressed(KeyEvent e){
        switch(e.getKeyCode()){
            case KeyEvent.VK_LEFT:
                leftMove();//调用左移的方法
                repaint();
                break;
            case KeyEvent.VK_RIGHT:
                rightMove();//调用右移的方法
                repaint();
                break;
            case KeyEvent.VK_DOWN:
                downMove();//调用左移的方法
                repaint();
                break;
            case KeyEvent.VK_UP:
                turnShape();//调用变形的方法
                repaint();
                break;
        }
    }

    public void keyReleased(KeyEvent e) {
    }
    public void keyTyped(KeyEvent e) {
    }
    //创建左移的方法
    public void leftMove(){
        if(judgeState(left-1,top,shapeType,shapeState)==1){
            left-=1;
        }
    }
    //创建右移的方法
    public void rightMove(){
        if(judgeState(left+1,top,shapeType,shapeState)==1){
            left+=1;
        };
    }
    //创建下移的方法
    public void downMove(){
        if(judgeState(left,top+1,shapeType,shapeState)==1){  //判断有图形
            top+=1;
            deleteLine();   //判断下移后是否有满行
        }
        if(judgeState(left,top+1,shapeType,shapeState)==0){   //判断没有图形

            addshape(left,top,shapeType,shapeState);
            createshape();
            deleteLine();
        }
    }
    //创建旋转变形的方法
    public void turnShape(){
        int tempshape=shapeState;
        shapeState=(shapeState+1)%4; //在四中的状态中选取
        if(judgeState(left,top,shapeType,shapeState)==1){

        }
        if(judgeState(left,top,shapeType,shapeState)==0){
            shapeState=tempshape;   //没有图形，不能进行旋转，还原原来状态
        }
        repaint();
    }

    public void paintComponent(Graphics g){
        super.paintComponent(g);
        int t=randomcolor.nextInt(5);
        int count=randomcolor.nextInt(5);
        Color[] color=new Color[]{Color.pink,Color.green,Color.red,Color.yellow,Color.blue};
        //绘制围墙
        for(j=0;j<22;j++){
            for(i=0;i<12;i++){
                if(map[i][j]==2){//判断是否为墙并绘制
                    g.setColor(Color.blue);
                    g.fill3DRect(i*CELL,j*CELL,CELL,CELL,true);
                }
                if(map[i][j]==0){//判断是否为墙并绘制
                    g.setColor(Color.red);
                    g.drawRoundRect(i*CELL,j*CELL,CELL,CELL,6,6);}
            }
        }
        //绘制正在下落的图形
        for(int k=0;k<16;k++){
            if(shapes[shapeType][shapeState][k]==1){
                g.setColor(Color.red);
                g.fill3DRect((left+k%4+1)*CELL,(top+k/4)*CELL,CELL,CELL,true);  //left\top为左上角的坐标
            }
        }
        //绘制落下的图形
        for(j=0;j<22;j++){
            for(i=0;i<12;i++){
                if(map[i][j]==1){
                    g.setColor(Color.green);
                    g.fill3DRect(i*CELL,j*CELL,CELL,CELL,true);
                }
            }
        }
        //显示右边预览图形
        for(int i = 0; i < 4; i++) {
            for(int j = 0; j < 4; j++){
                if(shapes[nextshapeType][nextshapeState][i*4+j] == 1) {
                    g.setColor(Color.red);
                    g.fill3DRect(375+(j*(CELL-10)),190+(i*(CELL-10)), CELL-10, CELL-10,true);
                }
            }
        }
        //添加右边预览图形方格
        for(int i = 0; i < 5; i++) {
            for(int j = 0; j < 5; j++){
                g.setColor(Color.blue);
                g.drawRoundRect(360+(j*(CELL-10)),175+(i*(CELL-10)),CELL-10, CELL-10,3,3);
            }
        }
        g.setFont(new Font("楷书",Font.BOLD,20));
        g.setColor(Color.BLACK);
        g.drawString("游戏分数:", 310, 70);
        g.setColor(Color.pink);
        g.drawString(score+" ", 420, 70);
        g.setColor(Color.BLACK);
        g.drawString("  分", 450, 70);
        g.setColor(Color.BLACK);
        g.setFont(new Font("黑体",Font.BOLD,14));
        g.drawString("提示：左击暂停,右击继续。", 305, 430);
        g.setColor(Color.blue);
        g.drawString("Next square", 358, 268);
    }
    //创建添加新图形到地图的方法
    public void addshape(int left,int top,int shapeType,int shapeState){
        int temp=0;
        for(int a=0;a<4;a++){
            for(int b=0;b<4;b++){   //对存储方块队的[4][4]数组遍历
                if(map[left+b+1][top+a]==0){ //表明[4][4]数组没有方块

                    map[left+b+1][top+a]=shapes[shapeType][shapeState][temp];
                }
                temp++;
            }
        }
    }

    public void deleteLine(){
        int tempscore=0;      //定义满行的列个数满足1
        for(int a=0;a<22;a++){   //对地图进行遍历
            for(int b=0;b<12;b++){
                if(map[b][a]==1){    //表示找到满行
                    tempscore++;     // 记录一行有多少个1
                    if(tempscore==10){
                        score+=10;
                        for(int k=a;k>0;k--){     //从满行开始回历
                            for(int c=1;c<12;c++){
                                map[c][k]=map[c][k-1];  //将图形整体下移一行
                            }
                        }
                    }
                }
            }
            tempscore=0;
        }
    }
    //判断游戏结束，1、判断新块的状态是否不存在，即judgeState()==0
//2、判断初始产生的位置是否一直为1；
    public int gameOver(int left,int top){
        if(judgeState(left,top,shapeType,shapeState)==0){
            return 1;
        }
        return 0;
    }
    //创建构造方法
    public GameBody(){
        resetMap();
        drawWall();
        createshape();
        //Timer timer=new Timer(1000,new TimeListener());
        Thread timer=new Thread(new	TimeListener());
        timer.start();
    }

    public void setStart(boolean start){   //改变start值的方法
        this.start=start;
    }
    //创建定时下落的监听器
    class TimeListener implements Runnable{
        public void run(){
            while(true){
                if(!start){
                    try{
                        repaint();
                        if(judgeState(left,top+1,shapeType,shapeState)==1){
                            top+=1;
                            deleteLine();}
                        if(judgeState(left,top+1,shapeType,shapeState)==0){
                            if(flag==1){
                                addshape(left,top,shapeType,shapeState);
                                deleteLine();
                                createshape();
                                flag=0;
                            }
                            flag=1;
                        }
                        Thread.sleep(800);
                    }catch(Exception e){
                        e.getMessage();
                    }
                }
            }
        }
    }
}